package com.sc.nft.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.annotation.UserRecordTimes;
import com.sc.nft.controller.request.*;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.*;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.NewSecondCollectionCommonService;
import com.sc.nft.service.SecondCollectionConfigService;
import com.sc.nft.service.SecondCollectionService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import com.sc.nft.util.ImageCode;
import com.sc.nft.util.RedisUtil;
import com.sc.nft.util.TokenUtil;
import com.sc.nft.util.ValidateCode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


/**
 * 二级市场
 *
 * @author Sun
 * @since 2022-11-22 13:00:00
 */

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/market")
@Api(tags = "二级市场")
public class SecondaryMarketController {

    private final SecondCollectionConfigDao secondCollectionConfigDao;
    private final SecondCollectionDao secondCollectionDao;
    private final PackageRecordDao packageRecordDao;
    private final PackageRuleDao packageRuleDao;
    private final StaticDataDao staticDataDao;
    private final SecondCollectionService secondCollectionService;
    private final NewSecondCollectionCommonService newSecondCollectionCommonService;
    private final RedisTemplate redisTemplate;
    private final DigitalCollectionDao digitalCollectionDao;
    private final FilterIncomeListDao filterIncomeListDao;
    private final RedisUtil redisUtil;
    private final SecondCollectionConfigService secondCollectionConfigService;
    private final UserInfoDao userInfoDao;
    private final ExitConsensusUserDao exitConsensusUserDao;
    private final UserRelevanceDao userRelevanceDao;

    @ApiOperation(value = "市场搜索", notes = "市场搜索", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/marketSearch", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<SecondaryMarketSearchVO> marketSearch(@Valid @RequestBody SecondaryMarketSearchDTO request) {
        return PageResult.success(secondCollectionConfigService.marketSearch(request));
    }

    @ApiOperation(value = "1.1品牌孵化配置列表(搜索可用)", notes = "品牌孵化配置列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/brandMarketConfigPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<BrandConfigVO> brandConfigPage(@Valid @RequestBody SecondCollectionRequest request) {
        return PageResult.success(secondCollectionConfigDao.brandConfigPage(request.getFirstTitle(), request.getShowLevel(), request.getUserCreatorId(), request.getSortType(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "1.2自由二级配置列表(搜索可用)", notes = "2自由二级配置列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/freeMarketPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<SecondCollectionConfigDTO> collectionPage(@Valid @RequestBody SecondCollectionRequest request) {
        return PageResult.success(secondCollectionConfigDao.freeMarketPage(request.getFirstTitle(), request.getShowLevel(), request.getUserCreatorId(), request.getSortType(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "2. 寄售列表", notes = "寄售列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/marketConsignPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MarketConsignPageDTO> marketConsignPage(@Valid @RequestBody MarketConsignPageRequest request) {

        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getById(request.getConfigId());
        if (ObjectUtil.isNull(secondCollectionConfig) || BooleanUtil.isFalse(secondCollectionConfig.getStatus())) {
            return PageResult.fail(ErrorCode.NOT_CON_SIGN);
        }
        return PageResult.success(secondCollectionDao.marketConsignPage(secondCollectionConfig.getCollectionId(), request.getSortType(), request.getPageNo(), request.getPageSize()));
    }


    @ApiOperation(value = "3.1 品牌孵化商品详情", notes = "品牌孵化商品详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/brandMarketDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<BrandMarketDetailsVO> brandMarketDetails(@Valid @RequestBody ConfigIdRequest request) {
        return PageResult.success(secondCollectionService.brandMarketDetails(request.getConfigId()));
    }

    @ApiOperation(value = "3.2 品牌孵化商品历史记录", notes = "品牌孵化商品历史记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/brandMarketHistoryDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<BrandMarketHistoryDetailsVO>> brandMarketHistoryRecord(@Valid @RequestBody ControllerIdRequest request) {
        return PageResult.success(secondCollectionService.brandMarketHistoryDetails(request.getControllerId()));
    }

    @ApiOperation(value = "3.3 自由二级商品详情", notes = "自由二级商品详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/freeMarketDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<SecondCollectionDetailVO> freeMarketDetails(@Valid @RequestBody ProductIdRequest request) {
        return Result.success(secondCollectionService.getDetailById(request.getProductId()));
    }

    @ApiOperation(value = "3.3 自由二级商品详情v3.7", notes = "自由二级商品详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/v3.7/freeMarketDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiImplicitParams(
            @ApiImplicitParam(name = "idRequest", value = "列表中configId", required = true, dataType = "IdRequest", paramType = "body")
    )
    @UserLogin
    public Result<SecondCollectionDetailV3_7VO> freeMarketDetails_v3_7(@Valid @RequestBody IdRequest idRequest) {
        return Result.success(secondCollectionService.freeMarketDetails_v3_7(idRequest.getId()));
    }

    @ApiOperation(value = "验证码校验取消频繁限制接口", notes = "验证码校验取消频繁限制接口", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/checkImage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result checkImage(@Valid @RequestBody GetSmsNewCodeRequest request) {
        UserInfo user = UserPool.getUser();
        if (Objects.isNull(user)) {
            return Result.fail(ErrorCode.ACCOUNT_NOT_EXIST);
        }
        String code = String.valueOf(redisUtil.get(TokenUtil.getRegisterValidateCode(user.getUserTel(), request.getType())));
        Long expireTime = redisTemplate.getExpire(TokenUtil.getRegisterValidateCode(user.getUserTel(), request.getType()));
        log.debug("剩余过期时间为：", expireTime);
        if (Objects.isNull(expireTime) || expireTime.equals(-2L)) {
            return Result.fail(ErrorCode.INVALID_VERIFICATION_CODE);
        }
        if (!StrUtil.equals(code, request.getVerifyCode())) {
            return Result.fail(ErrorCode.VERIFICATION_ERROR);
        }
        if (Objects.isNull(request.getInterfaceUrl())) {
            request.setInterfaceUrl("");
        }
        redisTemplate.delete(RedisKeyEnum.USER_REQUEST.getKey() + user.getId() + request.getInterfaceUrl());
        redisTemplate.delete(RedisKeyEnum.USER_REQUEST_PRE_VALUE.getKey() + user.getId() + request.getInterfaceUrl());
        return Result.success();
    }

    @ApiOperation(value = "获取验证码接口", notes = "获取验证码接口", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getPicCode", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public void getPicCode(@Valid @RequestBody GetSmsCodeRequest request, HttpServletResponse response) {
        UserInfo user = UserPool.getUser();
        if (Objects.isNull(user)) {
            throw new GlobalRunTimeException(ErrorCode.ACCOUNT_NOT_EXIST);
        }
        ImageCode imageCode = ValidateCode.createImageCode();
        redisUtil.set(TokenUtil.getRegisterValidateCode(user.getUserTel(), request.getType()), imageCode.getCode(), 5);
        try {
            ImageIO.write(imageCode.getImage(), "jpeg", response.getOutputStream());
        } catch (IOException e) {
            throw new GlobalRunTimeException("验证码生成失败！");
        }
    }

    @ApiOperation(value = "2. 寄售列表v3.7", notes = "寄售列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/v3.7/marketConsignPagev", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserRecordTimes
    @UserLogin
    public PageResult<MarketConsignPageV3_7VO> marketConsignPagev3_7(@Valid @RequestBody MarketConsignPageRequest request) {
        if (!UserPool.getUser().getIsSm()) {
            return PageResult.fail("请先完成实名认证");
        }

        if (!UserPool.getUser().getIsValid()) {
            String key = "USER_REQ2_TIME_" + UserPool.getUser().getId();
            redisTemplate.opsForValue().increment(key, 1);
            redisTemplate.expire(key, 30, TimeUnit.SECONDS);

            int o = Integer.parseInt(redisTemplate.opsForValue().get(key).toString());
            if (o > 800) {
                UserPool.getUser().setIsFreeze(true);
                userInfoDao.freeze(UserPool.getUser().getId());
                return PageResult.success();
            }
        }

        SecondCollectionConfig secondCollectionConfig = secondCollectionConfigDao.getById(request.getConfigId());
        if (ObjectUtil.isNull(secondCollectionConfig) || BooleanUtil.isFalse(secondCollectionConfig.getStatus())) {
            return PageResult.fail(ErrorCode.NOT_CON_SIGN);
        }
        Page<MarketConsignPageV3_7VO> result = null;
        StaticData marketKnockStatus = staticDataDao.getByType("market_knock_status");
        Long shareUserId = null;
        if (request.getShowShare()) {
            shareUserId = UserPool.getUser().getRecommendUserId();
        }
        if (StrUtil.equals(marketKnockStatus.getValue(), "1") && filterIncomeListDao.checkListIsFilterAccount(Lists.newArrayList(6L, 7L), UserPool.getUserId())) {
            result = secondCollectionDao.marketConsignPagev3_7ForMarket(shareUserId, secondCollectionConfig.getCollectionId(), request.getSortType(), request.getPageNo(), request.getPageSize());
        } else {
            result = secondCollectionDao.marketConsignPagev3_7(shareUserId, UserPool.getUser().getId(), secondCollectionConfig.getCollectionId(), request.getSortType(), request.getPageNo(), request.getPageSize());
        }
        //放入套餐权益状态
        for (MarketConsignPageV3_7VO data : result.getRecords()) {
            PackageRule packageRule = packageRuleDao.getOpenByCollectionId(secondCollectionConfig.getCollectionId());
            if (ObjectUtil.isNull(packageRule)) {
                continue;
            }
            PackageRecord record = packageRecordDao.getByCollectionUuid(data.getCollectionUuid());
            if (ObjectUtil.isNull(record)) {
                if (DateTime.now().isBefore(packageRule.getEndTime())) {
                    data.setPackageStatus(1);
                } else {
                    data.setPackageStatus(3);
                }
            } else {
                data.setPackageStatus(2);
            }
        }
        return PageResult.success(result);
    }


    @ApiOperation(value = "根据寄售id获取购买商品的数据v3.7", notes = "根据id获取购买商品的数据", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/v3.7/consignmentSalesIdGetParticulars", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<ConsignmentSalesIdGetParticularsVO> consignmentSalesIdGetParticulars(@Valid @RequestBody IdRequest idRequest) {
        ConsignmentSalesIdGetParticularsVO consignmentSalesIdGetParticularsVO = secondCollectionDao.consignmentSalesIdGetParticulars(idRequest.getId());
        consignmentSalesIdGetParticularsVO.setNowDate(DateUtil.now());
        return Result.success(consignmentSalesIdGetParticularsVO);
    }

    @ApiOperation(value = "1.2自由二级配置列表(搜索可用)v3.7", notes = "1.2自由二级配置列表(搜索可用)v3.7", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/v3.7/freeMarketPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<SecondCollectionConfigDTO> collectionPagev3_7(@Valid @RequestBody SecondCollectionRequest request) {

        if (!UserPool.getUser().getIsValid()) {
            String key = "USER_REQ_TIME_" + UserPool.getUser().getId();
            redisTemplate.opsForValue().increment(key, 1);
            redisTemplate.expire(key, 30, TimeUnit.SECONDS);

            int o = Integer.parseInt(redisTemplate.opsForValue().get(key).toString());
            if (o > 111) {
                UserPool.getUser().setIsFreeze(true);
                userInfoDao.freeze(UserPool.getUser().getId());
                return PageResult.success();
            }
        }
        return PageResult.success(secondCollectionConfigDao.freeMarketPagev3_7(request.getFirstTitle(), request.getShowLevel(), request.getUserCreatorId(), request.getSortType(), request.getPageNo(), request.getPageSize(), request.getStatus()));
    }


    @ApiOperation(value = "1.2自由二级配置列表(搜索可用)v5.4", notes = "1.2自由二级配置列表(搜索可用)v5.4", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/v5.4/freeMarketPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserRecordTimes
    @UserLogin
    public PageResult<SecondCollectionConfigDTO> collectionPage5_4(@Valid @RequestBody FreeMarketPageDTO freeMarketPageVO, HttpServletRequest httpServletRequest) {
        if (!UserPool.getUser().getIsValid()) {
            String key = "USER_REQ_TIME_" + UserPool.getUser().getId();
            redisTemplate.opsForValue().increment(key, 1);
            redisTemplate.expire(key, 30, TimeUnit.SECONDS);
            int o = Integer.parseInt(redisTemplate.opsForValue().get(key).toString());
            if (o > 111) {
                UserPool.getUser().setIsFreeze(true);
                userInfoDao.freeze(UserPool.getUser().getId());
                return PageResult.success();
            }
        }
        if (!UserPool.getUser().getIsSm() && UserPool.getUser().getRecommendUserId().intValue() == 1) {
            String key = "MARKET_REQUEST_IP_" + UserPool.getUser().getId();
            String clientIP = ServletUtil.getClientIP(httpServletRequest);
            List range = redisTemplate.opsForList().range(key, 0, -1);
            if (CollUtil.isNotEmpty(range)) {
                if (range.contains(clientIP)) {
                    redisTemplate.delete(key);
                } else {
                    redisTemplate.opsForList().rightPush(key, clientIP);
                }
                if (range.size() > 7) {
                    UserPool.getUser().setIsFreeze(true);
                    userInfoDao.freeze(UserPool.getUser().getId());
                }
            } else {
                redisTemplate.opsForList().rightPush(key, clientIP);
                redisTemplate.expire(key, 5, TimeUnit.MINUTES);
            }
        }
        ExitConsensusUser exitConsensusUser = exitConsensusUserDao.getByUserId(UserPool.getUser().getId());
        IPage<SecondCollectionConfigDTO> secondCollectionConfigDTOIPage = secondCollectionConfigDao.freeMarketPagev5_4(freeMarketPageVO);
        List<Long> ecologyCollectionIdList = digitalCollectionDao.getEcologyCollectionIdList();
        if (ObjectUtil.isNotNull(exitConsensusUser) && exitConsensusUser.getStatus()) {
            for (SecondCollectionConfigDTO record : secondCollectionConfigDTOIPage.getRecords()) {
                if (ecologyCollectionIdList.contains(record.getCollectionId())) {
                    record.setMinPrice(newSecondCollectionCommonService.getCacheMinPriceNotInConsensus(record.getCollectionId()));
                    record.setSalesCount(secondCollectionDao.getSalesCountByCollectionIdNotInConsensus(record.getCollectionId()));
                } else {
                    record.setMinPrice(newSecondCollectionCommonService.getCacheMinPrice(record.getCollectionId()));
                    record.setSalesCount(secondCollectionDao.getSalesCountByCollectionId(record.getCollectionId()));
                }
            }
            return PageResult.success(secondCollectionConfigDTOIPage);

        } else {
            for (SecondCollectionConfigDTO record : secondCollectionConfigDTOIPage.getRecords()) {
                if (ecologyCollectionIdList.contains(record.getCollectionId())) {
                    record.setMinPrice(newSecondCollectionCommonService.getCacheMinPriceForConsensus(record.getCollectionId()));
                    record.setSalesCount(secondCollectionDao.getSalesCountByCollectionIdForConsensus(record.getCollectionId()));

                } else {
                    record.setMinPrice(newSecondCollectionCommonService.getCacheMinPrice(record.getCollectionId()));
                    record.setSalesCount(secondCollectionDao.getSalesCountByCollectionId(record.getCollectionId()));
                }
            }
            return PageResult.success(secondCollectionConfigDTOIPage);

        }

    }
}
